package com.lcc.mysys.web.controller.admin;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.GifCaptcha;
import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import com.lcc.lynx.base.system.constant.MenuTypeConst;
import com.lcc.lynx.base.system.constant.StateConst;
import com.lcc.lynx.common.ResultVO;
import com.lcc.lynx.common.cache.GroupCache;
import com.lcc.lynx.common.utils.CheckUtil;
import com.lcc.lynx.security.Session;
import com.lcc.lynx.security.annotation.Anonymous;
import com.lcc.lynx.security.config.SecurityProperties;
import com.lcc.lynx.security.pojo.UserInfo;
import com.lcc.lynx.base.system.pojo.dv.SysMenuDV;
import com.lcc.lynx.base.system.pojo.dv.SysUserDV;
import com.lcc.lynx.base.system.service.SysMenuService;
import com.lcc.lynx.base.system.service.SysUserService;
import com.lcc.lynx.common.utils.RsaUtil;
import com.lcc.lynx.common.utils.StrUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.awt.*;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;


@RestController
@RequestMapping
@AllArgsConstructor
public class LoginController {

    private SysUserService sysUserService;

    private SysMenuService sysMenuService;

    private SecurityProperties securityProperties;

    @Anonymous
    @GetMapping("/captcha")
    public ResultVO captcha() {
        GifCaptcha gifCaptcha = CaptchaUtil.createGifCaptcha(150, 45);
        gifCaptcha.setGenerator(new RandomGenerator("0123456789", 4));
        gifCaptcha.setBackground(new Color(248, 248, 248));
        gifCaptcha.setMaxColor(60);
        gifCaptcha.setMinColor(55);
        UUID uuid = UUID.randomUUID();
        GroupCache.setVal("captcha:" + uuid, gifCaptcha.getCode(), 300);
        return ResultVO.successPut("uuid", uuid).put("base64Data", gifCaptcha.getImageBase64Data());
    }

    @RequestMapping("/login")
    public ResultVO<String> login(HttpServletRequest req, HttpServletResponse resp, SysUserDV userDV,
                                  String code, String uuid){

        StrUtil.isNotBlank("账号或密码不能为空", userDV.getLoginId(), userDV.getPassword());
        if(!"dev".equals(securityProperties.getEnv())){
            StrUtil.isNotBlank("验证码不能为空", code, uuid);

            Object val = GroupCache.getVal("captcha:" + uuid);
            if(val == null){
                return ResultVO.fail("验证码已过期");
            }
            if(!val.toString().equalsIgnoreCase(code)){
                return ResultVO.fail("验证码错误");
            }
        }


        SysUserDV sysUserDV = new SysUserDV();
        sysUserDV.setLoginId(userDV.getLoginId());

        SysUserDV user = sysUserService.selectOne(sysUserDV);
        if(user == null){
            return ResultVO.fail("账号不存在");
        }
        String pwd = RsaUtil.decrypt(userDV.getPassword(), KeyType.PrivateKey);
        String md5Pwd = SecureUtil.hmacMd5(securityProperties.getMd5Key()).digestHex(pwd);
        if(!user.getPassword().equals(md5Pwd)){
            return ResultVO.fail("密码错误");
        }
        UserInfo<SysUserDV> userInfo = new UserInfo<>();
        userInfo.setUser(user);

        // 设置角色列表
        userInfo.setRoles(sysUserService.getMapper().queryUserRoles(user));
        userInfo.setAdmin(userInfo.getRoles().contains("ADMIN"));
        userInfo.setLogin(true);
        if(!userInfo.isAdmin()){
            // 设置权限列表
            userInfo.setPermissions(sysUserService.queryUserPermissions(user));
        }
        Session.set(userInfo, req, resp);

        SysUserDV update = new SysUserDV();
        update.setUserId(user.getUserId());
        update.setLastLoginTime(new Date());
        sysUserService.updateById(update);

        return ResultVO.success(userInfo.getToken());
    }

    @RequestMapping("/getUserInfo")
    public ResultVO<UserInfo> getUserInfo(){
        return ResultVO.success(Session.getUserInfo());
    }

    @RequestMapping("/getMenuByUser")
    public ResultVO<List<SysMenuDV>> getMenuByUser(SysUserDV dv){
        UserInfo<SysUserDV> userInfo = Session.getUserInfo();
        if(userInfo != null){
            if(userInfo.isAdmin()){
                SysMenuDV sysMenuDV = new SysMenuDV();
                sysMenuDV.setMenuTypeInList(Arrays.asList(MenuTypeConst.DIRECTORY, MenuTypeConst.MENU));
                sysMenuDV.setOrderBy("sort");
                return ResultVO.success(sysMenuService.getMapper().select(sysMenuDV));
            }else{
                dv.setUserId(userInfo.getUser().getUserId());
                return ResultVO.success(sysMenuService.getMapper().getMenuByUser(dv));
            }
        }
        if(dv.getUserId() == null){
            return ResultVO.fail("登录身份过期！");
        }
        return ResultVO.success(sysMenuService.getMapper().getMenuByUser(dv));
    }

    @RequestMapping("/logout")
    public ResultVO<?> logout(){
        Session.logout();
        return ResultVO.success();
    }

    @Anonymous
    @RequestMapping("/register")
    public ResultVO<?> register(SysUserDV userDV){
        CheckUtil checkUtil = CheckUtil.of(userDV);
        String errorMsg = checkUtil
                .check(userDV::getLoginId, "账号")
                .check(userDV::getPassword, "密码")
                .check(userDV::getUsername, "用户名")
                .checkRegEx1(userDV::getPhone, "手机号", "^1[3-9]\\d{9}$", "手机号格式错误")
                .getErrorMsg();
        if(StrUtil.isNotBlank(errorMsg)){
            return ResultVO.fail(errorMsg);
        }
        SysUserDV sysUserDV = new SysUserDV();
        sysUserDV.setLoginId(userDV.getLoginId());

        SysUserDV user = sysUserService.selectOne(sysUserDV);
        if(user != null){
            return ResultVO.fail("账号已存在");
        }
        String pwd = RsaUtil.decrypt(userDV.getPassword(), KeyType.PrivateKey);
        String regex = securityProperties.getPasswordRegex();
        if(StrUtil.isNotEmpty(regex) && !pwd.matches(regex)){
            return ResultVO.fail(securityProperties.getPasswordRegexMsg());
        }

        String md5Pwd = SecureUtil.hmacMd5(securityProperties.getMd5Key()).digestHex(pwd);
        userDV.setPassword(md5Pwd);
        userDV.setState(StateConst.NORMAL);
        sysUserService.addAndRole(userDV);
        return ResultVO.success();
    }

    @Anonymous
    @RequestMapping("/checkLoginId")
    public ResultVO<Boolean> checkLoginId(@RequestParam("loginId") String loginId){
        SysUserDV sysUserDV = new SysUserDV();
        sysUserDV.setLoginId(loginId);

        SysUserDV user = sysUserService.selectOne(sysUserDV);
        return ResultVO.success(user != null);
    }
}
